//
//  HKCollectionAdapter.m
//  KSBridgeDesign
//
//  Created by huzhaoke on 2021/6/3.
//

#import "HKCollectionAdapter.h"
#import "HKListCellModel.h"
#import "HKListSectionModel.h"
#import "HKListAdapter+Private.h"
#import "HKListSectionModel+Private.h"
#import "HKListCellModel+Private.h"
#import "HKSectionHeaderFooterViewModel.h"

static NSString * const HKAdapterErrorHeaderFooterIdentifier = @"ks_header_footer_error_identifier";


@interface HKCollectionAdapter () <UICollectionViewDataSource, UICollectionViewDelegate>

@property (nonatomic, weak) UICollectionView *collectionView;

@end


@implementation HKCollectionAdapter

- (void)dealloc {
    _collectionView.delegate = nil;
    _collectionView.dataSource = nil;
}

- (instancetype)initWithCollectionView:(UICollectionView *)collectionView {
    return [self initWithView:collectionView];
}

- (instancetype)initWithView:(UICollectionView *)collectionView {
    self = [super initWithView:collectionView];
    if (self) {
        _collectionView = collectionView;
        collectionView.delegate = self;
        collectionView.dataSource = self;
        [self registerDefaultIdentifiers];
    }
    return self;
}

#pragma mark - Reload Cells
- (void)reloadCellModel:(HKListCellModel *)cellModel completion:(ReloadCompleteBlock)completion {
    NSIndexPath *indexPath = [self indexPathOfCellModel:cellModel];
    if (!indexPath) {
        return;
    }
    
    if (![self.collectionView.indexPathsForVisibleItems containsObject:indexPath]) {
        return;
    }
    
    [self performBatchUpdates:^(HKCollectionAdapter *adapter) {
        [adapter.collectionView reloadItemsAtIndexPaths:@[indexPath]];
    } animated:NO completion:completion];
}

- (void)reloadSectionModel:(HKListSectionModel *)sectionModel completion:(void (^ _Nullable)(BOOL finished))completion {
    NSUInteger section = [self.sectionModels indexOfObject:sectionModel];
    if (section == NSNotFound) {
        return;
    }
    
    [self performBatchUpdates:^(HKCollectionAdapter *adapter) {
        [adapter.collectionView reloadSections:[NSIndexSet indexSetWithIndex:section]];
    } animated:NO completion:completion];
}

#pragma mark - Animation Batch Updates
- (void)performBatchUpdates:(void (NS_NOESCAPE ^)(HKCollectionAdapter *adapter))updates
                   animated:(BOOL)animated
                 completion:(void (^ _Nullable)(BOOL finished))completion {
    [UIView setAnimationsEnabled:animated];
    [self.collectionView performBatchUpdates:^{
        if (updates) {
            updates(self);
        }
    } completion:^(BOOL finished) {
        if (completion) {
            completion(finished);
        }
        [UIView setAnimationsEnabled:YES];
    }];
}

#pragma mark - Manage Identifiers
- (void)registerDefaultIdentifiers {
    [self.collectionView registerClass:UICollectionReusableView.class
            forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                   withReuseIdentifier:HKAdapterErrorHeaderFooterIdentifier];
    
    [self.collectionView registerClass:UICollectionReusableView.class
            forSupplementaryViewOfKind:UICollectionElementKindSectionFooter
                   withReuseIdentifier:HKAdapterErrorHeaderFooterIdentifier];
}

- (void)registerCellModel:(HKListCellModel *)cellModel {
    NSString *identifier = cellModel.identifier;
    if (!identifier || [self containsCellIdentifier:identifier]) {
        return;
    }
    [self.collectionView registerClass:cellModel.cellClass forCellWithReuseIdentifier:identifier];
    [self addCellIdentifier:identifier];
}

- (void)registerHeaderFooterItem:(HKSectionHeaderFooterViewModel *)headerFooterItem kind:(NSString *)kind {
    NSString *identifier = headerFooterItem.identifier;
    NSString *setKey = [NSString stringWithFormat:@"%@|%@", kind, identifier];
    if (!identifier || [self containsHeaderFooterIdentifier:setKey]) {
        return;
    }
    [self.collectionView registerClass:headerFooterItem.viewClass forSupplementaryViewOfKind:kind withReuseIdentifier:identifier];
    [self addHeaderFooterIdentifier:setKey];
}

#pragma mark - UICollectionViewDataSource
- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
    HKListSectionModel *sectionModel = [self sectionModelInSection:indexPath.section];
    NSAssert(sectionModel, @"sectionItem不能为空");
    if (!sectionModel) { // Protection
        return [self errorCell];
    }
    __weak typeof(self) weakSelf = self;
    [sectionModel setReloadBlock:^(HKListSectionModel * _Nonnull sectionModel, NSIndexPath * _Nonnull indexPath, UITableViewRowAnimation animation, void (^ _Nullable completion)(BOOL)) {
        [weakSelf reloadSectionModel:sectionModel completion:completion];
    }];
    
    
    HKListCellModel *cellIModel = [sectionModel cellModelAtIndex:indexPath.row];
    NSAssert(cellIModel, @"cellItem不能为空");
    if (!cellIModel) { // Protection
        return [self errorCell];
    }
    [self registerCellModel:cellIModel];
    [cellIModel setReloadBlock:^(HKListCellModel *cellModel, NSIndexPath *indexPath, UITableViewRowAnimation animation, ReloadCompleteBlock completion) {
        [weakSelf reloadCellModel:cellModel completion:completion];
    }];
    
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIModel.identifier forIndexPath:indexPath];
    NSAssert(cell, @"cell不能为空, 请检查identifier");
    if (!cell) { // Protection
        return [self errorCell];
    }
    
    cellIModel.sectionModel = sectionModel;
    cellIModel.render(cellIModel, cell);
    
    return cell;
}

- (nonnull UICollectionViewCell *)errorCell {
    UICollectionViewCell *cell = [[UICollectionViewCell alloc] init];
    return cell;
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return [self sectionCount];
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return [self cellCountInSection:section];
}

- (HKSectionHeaderFooterViewModel *)headerFooterItemForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
    HKListSectionModel *sectionModel = [self sectionModelInSection:indexPath.section];
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
        return sectionModel.headerViewModel;
    } else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) {
        return sectionModel.footerViewModel;
    } else {
        return nil;
    }
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
    
    HKSectionHeaderFooterViewModel *item = [self headerFooterItemForSupplementaryElementOfKind:kind atIndexPath:indexPath];
    [self registerHeaderFooterItem:item kind:kind];
    
    UICollectionReusableView *view = [self.collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:item.identifier forIndexPath:indexPath];
    
    if (!view) {
        view = [self.collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:HKAdapterErrorHeaderFooterIdentifier forIndexPath:indexPath];
        return view;
    }
    
    item.render(item, view);
    
    return view;
}

#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    [collectionView deselectItemAtIndexPath:indexPath animated:YES];
    HKListCellModel *cellModel = [self cellModelAtIndexPath:indexPath];
    if (cellModel.cellDidSelectBlock) {
        UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
        cellModel.cellDidSelectBlock(cellModel, indexPath.copy, cell);
    }
}

- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
    HKListCellModel *cellModel = [self cellModelAtIndexPath:indexPath];
    if (cellModel.cellWillDisplayBlock) {
        cellModel.cellWillDisplayBlock(cellModel, indexPath.copy, cell);
    }
}

- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
    HKListCellModel *cellModel = [self cellModelAtIndexPath:indexPath];
    if (cellModel.cellDidEndDisplayBlock) {
        cellModel.cellDidEndDisplayBlock(cellModel, indexPath.copy, cell);
    }
}

- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
    HKListCellModel *cellModel = [self cellModelAtIndexPath:indexPath];
    if (cellModel.cellDidHighlightBlock) {
        UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
        cellModel.cellDidHighlightBlock(cellModel, indexPath.copy, cell);
    }
}
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath {
    HKListCellModel *cellModel = [self cellModelAtIndexPath:indexPath];
    if (cellModel.cellDidUnhighlightBlock) {
        UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
        cellModel.cellDidUnhighlightBlock(cellModel, indexPath.copy, cell);
    }
}


- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
    
}

- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
    
}

#pragma mark - UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    HKListCellModel *cellModel = [self cellModelAtIndexPath:indexPath];
    if (cellModel.cellWidthBlock) {
        //  同时也更新一下cellItem 的cellSize
        CGFloat cellWidth = cellModel.cellWidthBlock();
        cellModel.cellWidth = MAX(cellWidth, 0);
    }
    
    return CGSizeMake(cellModel.cellWidth, cellModel.cellHeight);
}

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
    referenceSizeForHeaderInSection:(NSInteger)section {
    HKSectionHeaderFooterViewModel *header = [self sectionModelInSection:section].headerViewModel;
    if (!header) {
        return CGSizeZero;
    }
    
    return CGSizeMake(header.width, header.height);
}

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
    referenceSizeForFooterInSection:(NSInteger)section {
    HKSectionHeaderFooterViewModel *footer = [self sectionModelInSection:section].footerViewModel;
    if (!footer) {
        return CGSizeZero;
    }
    return CGSizeMake(footer.width, footer.height);
}


@end
